package com.jkt.rms.controller;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;

import com.jkt.rms.business.Project;
import com.jkt.rms.businessservice.ProjectBusinessService;
import com.jkt.rms.commons.utils.RMSException;
import com.jkt.rms.vo.ProjectVO;

public class ProjectController extends AbstractMultiActionController {
	private ProjectBusinessService projectBusinessService;
	
	private static final Logger LOG = Logger.getLogger(ProjectController.class);
	
	public void setProjectBusinessService(
			ProjectBusinessService projectBusinessService) {
		this.projectBusinessService = projectBusinessService;
	}
	
	protected void bind(HttpServletRequest request, Object command)
	 {
		final ServletRequestDataBinder binder = new ServletRequestDataBinder(command);
		final String dateformat = request.getSession().getServletContext().getInitParameter("dateformat");
		LOG.info("dateformat : " + dateformat);
		final DateFormat dateFormat = new SimpleDateFormat(dateformat);
		final CustomDateEditor dateEditor = new CustomDateEditor(dateFormat, true){
			public Object getValue() {
				final Date date = (Date) super.getValue();
				return  date != null ? new Timestamp(date.getTime()) : null;
			}
		};
		
		final CustomNumberEditor longEditor = new CustomNumberEditor(Long.class, true);
		final CustomNumberEditor integerEditor = new CustomNumberEditor(Integer.class, true);

		binder.registerCustomEditor(Timestamp.class, dateEditor);
		binder.registerCustomEditor(Long.class, longEditor);
		binder.registerCustomEditor(Integer.class, integerEditor);
		binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
		binder.bind(request);
		errors = binder.getBindingResult();

}

	
	public ModelAndView addSearchProjectUI(HttpServletRequest request,
			HttpServletResponse response) throws RMSException {
		LOG.info("addProject(...) invoked");
		final Map<String, Object> model = new HashMap<String, Object>();
		final ProjectVO addProjectVO = new ProjectVO();
		final ProjectVO searchProjectVO = new ProjectVO();
		model.put("addProjectVO", addProjectVO);
		model.put("searchProjectVO", searchProjectVO);
		return new ModelAndView("addSearchProject", model);
	}

//	public ModelAndView addProjectUI(HttpServletRequest request,
//			HttpServletResponse response) throws RMSException {
//		LOG.info("addProject(...) invoked");
//		final Map<String, Object> model = new HashMap<String, Object>();
//		final ProjectVO projectVO = new ProjectVO();
//		model.put("projectVO", projectVO);
//		return new ModelAndView("addProject", model);
//	}
	
	public ModelAndView saveProject(HttpServletRequest request,
			HttpServletResponse response) throws RMSException {
		LOG.info("saveProject(...) invoked");
		
		ProjectVO projectVO = new ProjectVO();
		bind(request, projectVO);
		final Map<String, Object> model = new HashMap<String, Object>();
		validate(projectVO);
		
		if (!(errors != null && errors.getAllErrors() != null
				&& errors.getAllErrors().size() > 0)) {
			//no error/validation so save Project
			projectVO = projectBusinessService.saveProject(projectVO);
			model.put("infoMsg", projectVO.getInfoMessage());
			projectVO = new ProjectVO();
		}else{
			model.put("errors", errors);
		}
		
		model.put("addProjectVO", projectVO);
		model.put("searchProjectVO", new ProjectVO());
		return new ModelAndView("addSearchProject", model);
	}
	
//	public ModelAndView searchProjectUI(HttpServletRequest request,
//			HttpServletResponse response) throws RMSException {
//		LOG.info("searchProject(...) invoked");
//		ProjectVO projectVO = new ProjectVO();
//		return new ModelAndView("searchProject", "projectVO", projectVO);
//	}

	public ModelAndView searchProjects(HttpServletRequest request,
			HttpServletResponse response) throws RMSException {
		LOG.info("searchProjects(...) invoked");
		
		final ProjectVO projectVO = new ProjectVO();
		final ServletRequestDataBinder binder = new ServletRequestDataBinder(projectVO);
		binder.bind(request);
		//set search related information in sesssion
		request.getSession().setAttribute("SearchCriteria", projectVO);
		final Map<String, Object> model = new HashMap<String, Object>();
		model.put("searchProjectVO", projectVO);
		model.put("addProjectVO", new ProjectVO());
		final List<Project> list = projectBusinessService.searchProjects(projectVO);
		if(list == null || list.size() == 0){
			model.put("infoMsg", "No result found for given criteria.");
		}
		return new ModelAndView("addSearchProject", model).addObject("searchResult", list);
	}
	
	public ModelAndView searchAllProjects(HttpServletRequest request,
			HttpServletResponse response) throws RMSException {
		
		LOG.info("searchAllProjects(...) invoked");
		final ProjectVO projectVO = new ProjectVO();
		final ServletRequestDataBinder binder = new ServletRequestDataBinder(projectVO);
		binder.bind(request);
		//set search related information
		request.getSession().setAttribute("SearchCriteria", projectVO);
		final Map<String, Object> model = new HashMap<String, Object>();
		final List<Project> list = projectBusinessService.searchProjects(null);
		model.put("searchProjectVO", projectVO);
		model.put("addProjectVO", new ProjectVO());
		return new ModelAndView("addSearchProject", model).addObject("searchResult", list);
	}	

	public ModelAndView updateProjectUI(HttpServletRequest request,
			HttpServletResponse response) throws RMSException {
		
		LOG.info("updateProject(...) invoked");
		final String projectId = request.getParameter("id");
		final Project project = projectBusinessService.findProjectById(Integer.parseInt(projectId));
		final ProjectVO projectVO = new ProjectVO();
		
		BeanUtils.copyProperties(project, projectVO);
		final Map<String, Object> model = new HashMap<String, Object>();
		model.put("projectVO", projectVO);
		return new ModelAndView("updateProject", model);
	}	

	public ModelAndView saveUpdatedProject(HttpServletRequest request,
			HttpServletResponse response) throws RMSException {
		
		LOG.info("saveUpdatedProject(...) invoked");
		
		ProjectVO projectVO = new ProjectVO();
		bind(request, projectVO);
		final Map<String, Object> model = new HashMap<String, Object>();
		validate(projectVO);
		if (!(errors != null && errors.getAllErrors() != null
				&& errors.getAllErrors().size() > 0)) {
			//update Project
			projectBusinessService.updateProject(projectVO);
			//fetch projectVO from session because we need to display search page because data update successfully
			projectVO = (ProjectVO) request.getSession().getAttribute("SearchCriteria");
			populateSearchResult(projectVO,model);
			model.put("searchProjectVO", projectVO);
			model.put("addProjectVO", new ProjectVO());
			return new ModelAndView("addSearchProject", model);
		}else{
			model.put("errors", errors);
			model.put("projectVO", projectVO);
		}
		return new ModelAndView("updateProject", model);
	}

	public ModelAndView cancelUpdateProject(HttpServletRequest request,
			HttpServletResponse response) throws RMSException {
		
		LOG.info("saveUpdatedProject(...) invoked");
		
		ProjectVO projectVO = new ProjectVO();
		bind(request, projectVO);
		final Map<String, Object> model = new HashMap<String, Object>();
			//fetch projectVO from session because we need to display search page because data update successfully
		projectVO = (ProjectVO) request.getSession().getAttribute("SearchCriteria");
		populateSearchResult(projectVO,model);
		model.put("searchProjectVO", projectVO);
		model.put("addProjectVO", new ProjectVO());
		return new ModelAndView("addSearchProject", model);
		
		
	}
	
	private void populateSearchResult(ProjectVO projectVO,Map<String, Object> model) {
		List<Project> list = null;
		if(projectVO != null){
			//search criteria basis
			list = projectBusinessService.searchProjects(projectVO);
		}else{
			//find all
			list = projectBusinessService.searchProjects(null);
		}
		if(list == null || list.size() == 0){
			model.put("infoMsg", "No result found for given criteria.");
		}else{
			model.put("searchResult", list);
		}
	}	

}



